package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer2 {
    //clientSocket就是内场服务的小姐姐，每个客户端都会有一个这样服务的人
    //serversocket只有一个，是负责在外场拉客的人
    private ServerSocket serverSocket = null;

    public TcpEchoServer2(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动！");
        while (true) {
            //accept方法就是客户端来一个请求服务器就接受连接，然后就会分配一个socket文件去进行传输响应的数据
            Socket clientSocket = serverSocket.accept();
            Thread t1 = new Thread(() -> {
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            t1.start();
        }
    }
    //通过这个方法来处理一个连接   1.读取请求  2.根据读取请求的数据计算响应  3.把响应结果发送回给客户端
    //tcp是面向字节流的，所以在读数据的时候是通过scoket中的input和output方法来读取数据的
    private void processConnection(Socket clientSocket) throws IOException {
        //处理请求之前先显示一下，哪一台设备上线了
        System.out.printf("[%s:%d] 客户端上线！\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //try（）这种写法，（ ）允许写多个流，每个流是用 ; 来进行分割的
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            /*但是它读数据是从哪到哪里算是一个请求的数据呢，此时就约定每读到一个\n 就是一个请求*/
            Scanner scanner = new Scanner(inputStream);//scanner是以字符流处理数据的
            PrintWriter printWriter = new PrintWriter(outputStream);//他的意思就是把outputStream（字节流）变成字符串
            //然后循环处理请求，因为每个客户端可能有N个请求
            while (true) {
                //1.读取请求
                if (!scanner.hasNext()) {//scanner和printWriter只是一个套壳操作，读写数据的时候还是字节流读写数据
                    //将字节流转换为字符串处理
                    System.out.printf("[%s:%d] 客户端下线！\n" ,clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                //没读到数据的结尾，直接使用scanner来读一串字符串（一直读数据）
                String request = scanner.next();
                //2.计算响应
                String response = process(request);
                //3.把响应写回到客户端  注意：客户端在缓冲区读数据的时候也是要用\n来标识一下的
                //已经包装过了，所以就按字符流进行返回即可
                printWriter.println(request);
                printWriter.flush();
                System.out.printf("[%s:%d] req: %s, resp:%s\n",clientSocket.getInetAddress(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer2 tcpEchoServer2 = new TcpEchoServer2(9090);
        tcpEchoServer2.start();
    }

}
